# -*- coding: utf-8 -*-
# @Author  : Chen Yuanfei
# @Time    : 2023/12/12 13:24
# @Function:主函数

from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5 import uic
import sys, time
from PyQt5.QtCore import QThread, pyqtSignal


#pyqt主窗口类
class PyShine_THREADS_APP(QtWidgets.QMainWindow):
    #初始化函数
    #在定义类时，我们是没有对象的，类都还在定义中哪里去创建对象，所以这时我们规定统一用一个self来指定类的实例，这样我们就才能定义一些类的方法。
    #self只有在类的方法中才会有，独立的函数或方法是不必带有self的。self在定义类的方法时是必须有的，虽然在调用时不必传入相应的参数。
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        self.ui = uic.loadUi('threads.ui', self)
        self.resize(888, 200)
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap("PyShine.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.setWindowIcon(icon)
        #线程字典
        self.thread = {}

        #按钮功能函数绑定
        self.pushButton.clicked.connect(self.start_worker_1)
        self.pushButton_2.clicked.connect(self.start_worker_2)
        self.pushButton_3.clicked.connect(self.start_worker_3)
        self.pushButton_4.clicked.connect(self.stop_worker_1)
        self.pushButton_5.clicked.connect(self.stop_worker_2)
        self.pushButton_6.clicked.connect(self.stop_worker_3)

    #开始按钮绑定的函数，self指的是实例化的这个对象
    def start_worker_1(self):
        #实例化一个线程
        self.thread[1] = ThreadClass(parent=None, index=1)
        #启动线程，会自动执行在线程类中定义的run方法
        self.thread[1].start()
        #信号接收并绑定到qt窗口对象对应方法
        self.thread[1].any_signal.connect(self.my_function)
        #关闭按钮使能
        self.pushButton.setEnabled(False)
    #停止按钮绑定的函数
    def stop_worker_1(self):
        #线程停止
        self.thread[1].stop()
        #按钮激活使能
        self.pushButton.setEnabled(True)


    def start_worker_2(self):
        #实例化线程对象
        self.thread[2] = ThreadClass(parent=None, index=2)
        #开启线程，自动执行run方法，会自动传递出信号
        self.thread[2].start()
        #信号接收
        self.thread[2].any_signal.connect(self.my_function)
        self.pushButton_2.setEnabled(False)
    def start_worker_3(self):
        self.thread[3] = ThreadClass(parent=None, index=3)
        self.thread[3].start()
        self.thread[3].any_signal.connect(self.my_function)
        self.pushButton_3.setEnabled(False)
    def stop_worker_2(self):
        self.thread[2].stop()
        self.pushButton_2.setEnabled(True)
    def stop_worker_3(self):
        self.thread[3].stop()
        self.pushButton_3.setEnabled(True)


    #进度条设置
    def my_function(self, counter):
        cnt = counter
        index = self.sender().index
        if index == 1:
            self.progressBar.setValue(cnt)
        if index == 2:
            self.progressBar_2.setValue(cnt)
        if index == 3:
            self.progressBar_3.setValue(cnt)


#线程类
class ThreadClass(QtCore.QThread):
    #自定义信号
    any_signal = pyqtSignal(int)
    # 自定义信号对象。参数str就代表这个信号可以传一个字符串
    #trigger = pyqtSignal(str)
    '''
    "parent"：这是一个可选的参数，通常用于指定该线程与哪个父对象相关联。在PyQt5中，如果一个对象有一个父对象，则当父对象被删除时，
              所有相关的子对象也会被删除。如果不需要将线程与任何特定的对象关联起来，可以将其设置为None。
    "index"：这个参数是用于标识当前线程的唯一索引值。它可以用于区分多个线程实例，并且可以通过self.index属性来访问它。
    '''
    def __init__(self, parent=None, index=0):
        #线程初始化
        super(ThreadClass, self).__init__(parent)

        self.index = index
        self.is_running = True

    def run(self):
        print('Starting thread...', self.index)
        cnt = 0
        while (True):
            cnt += 1
            if cnt == 99:
                cnt = 0
            time.sleep(0.01)
            '''
            在PyQt5中，emit函数是一个信号发射器，用于向其他线程或部件发送信息。它通常与自定义信号一起使用，以允许不同部分的代码之间进行通信。
            当这个信号被发射时，所有已连接到该信号的对象都会接收到这个信号，并调用相应的槽函数来处理这个信号。
            需要注意的是，发射信号并不会阻塞程序的执行，而是立即返回并继续执行后面的代码。
            因此，在发射信号之前，需要确保所有必要的数据都已经准备好，否则可能会导致错误或者不正确的结果
            '''
            self.any_signal.emit(cnt)

    def stop(self):
        self.is_running = False
        print('Stopping thread...', self.index)
        self.terminate()




class TheadDemo(QThread):
    def __init__(self):
        super(TheadDemo, self).__init__()

    def run(self):
        pass






if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    # 创建窗体对象
    mainWindow = PyShine_THREADS_APP()
    # 对象方法：展示窗口
    mainWindow.show()
    # 系统退出
    sys.exit(app.exec_())



